{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Import"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Installing packages:\n",
      "\t.package(url: \"https://github.com/JacopoMangiavacchi/SwiftCoreMLTools.git\", from: \"0.0.3\")\n",
      "\t\tSwiftCoreMLTools\n",
      "\t.package(url: \"https://github.com/dduan/Just.git\", from: \"0.8.0\")\n",
      "\t\tJust\n",
      "With SwiftPM flags: ['-c', 'release']\n",
      "Working in: /tmp/tmpl6yib27l/swift-install\n",
      "Fetching https://github.com/JacopoMangiavacchi/SwiftCoreMLTools.git\n",
      "Fetching https://github.com/dduan/Just.git\n",
      "Fetching https://github.com/apple/swift-protobuf.git\n",
      "Cloning https://github.com/apple/swift-protobuf.git\n",
      "Resolving https://github.com/apple/swift-protobuf.git at 1.8.0\n",
      "Cloning https://github.com/dduan/Just.git\n",
      "Resolving https://github.com/dduan/Just.git at 0.8.0\n",
      "Cloning https://github.com/JacopoMangiavacchi/SwiftCoreMLTools.git\n",
      "Resolving https://github.com/JacopoMangiavacchi/SwiftCoreMLTools.git at 0.0.5\n",
      "[1/3] Compiling Just Just.swift\n",
      "[2/3] Compiling SwiftProtobuf AnyMessageStorage.swift\n",
      "[3/4] Compiling SwiftCoreMLTools Activations.swift\n",
      "[4/5] Compiling jupyterInstalledPackages jupyterInstalledPackages.swift\n",
      "[5/5] Linking libjupyterInstalledPackages.so\n",
      "Initializing Swift...\n",
      "Installation complete!\n"
     ]
    }
   ],
   "source": [
    "%install-swiftpm-flags -c release\n",
    "%install '.package(url: \"https://github.com/JacopoMangiavacchi/SwiftCoreMLTools.git\", from: \"0.0.5\")' SwiftCoreMLTools\n",
    "%install '.package(url: \"https://github.com/dduan/Just.git\", from: \"0.8.0\")' Just"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "colab": {},
    "colab_type": "code",
    "id": "TO4FT9bUohHx"
   },
   "outputs": [],
   "source": [
    "import Foundation\n",
    "import TensorFlow\n",
    "import SwiftCoreMLTools\n",
    "import Just"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Data Download\n",
    "\n",
    "Boston house prices dataset\n",
    "---------------------------\n",
    "\n",
    "**Data Set Characteristics:**  \n",
    "\n",
    "    :Number of Instances: 506 \n",
    "\n",
    "    :Number of Attributes: 13 numeric/categorical predictive. Median Value (attribute 14) is usually the target.\n",
    "\n",
    "    :Attribute Information (in order):\n",
    "        - CRIM     per capita crime rate by town\n",
    "        - ZN       proportion of residential land zoned for lots over 25,000 sq.ft.\n",
    "        - INDUS    proportion of non-retail business acres per town\n",
    "        - CHAS     Charles River dummy variable (= 1 if tract bounds river; 0 otherwise)\n",
    "        - NOX      nitric oxides concentration (parts per 10 million)\n",
    "        - RM       average number of rooms per dwelling\n",
    "        - AGE      proportion of owner-occupied units built prior to 1940\n",
    "        - DIS      weighted distances to five Boston employment centres\n",
    "        - RAD      index of accessibility to radial highways\n",
    "        - TAX      full-value property-tax rate per ten thousand dollars\n",
    "        - PTRATIO  pupil-teacher ratio by town\n",
    "        - B        1000(Bk - 0.63)^2 where Bk is the proportion of blacks by town\n",
    "        - LSTAT    % lower status of the population\n",
    "        - MEDV     Median value of owner-occupied homes in a thousand dollar\n",
    "\n",
    "    :Missing Attribute Values: None\n",
    "\n",
    "    :Creator: Harrison, D. and Rubinfeld, D.L.\n",
    "\n",
    "This is a copy of UCI ML housing dataset.\n",
    "https://archive.ics.uci.edu/ml/machine-learning-databases/housing/\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "// !wget -O \"../data/housing.csv\" https://archive.ics.uci.edu/ml/machine-learning-databases/housing/housing.data\n",
    "\n",
    "if let cts = Just.get(URL(string: \"https://archive.ics.uci.edu/ml/machine-learning-databases/housing/housing.data\")!).content {\n",
    "    try! cts.write(to: URL(fileURLWithPath:\"../data/housing.csv\"))\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Data Ingestion"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Training shapes [405 13] [405 1]\r\n",
      "Testing shapes  [101 13] [101 1]\r\n"
     ]
    }
   ],
   "source": [
    "// TODO: Download housing.csv\n",
    "\n",
    "let data = try String(contentsOfFile:\"../data/housing.csv\", encoding: String.Encoding.utf8)\n",
    "let dataRecords: [[Float]] = data.split(separator: \"\\n\").map{ String($0).split(separator: \" \").compactMap{ Float(String($0)) } }\n",
    "\n",
    "let numRecords = dataRecords.count\n",
    "let numColumns = dataRecords[0].count\n",
    "\n",
    "let dataFeatures = dataRecords.map{ Array($0[0..<numColumns-1]) }\n",
    "let dataLabels = dataRecords.map{ Array($0[(numColumns-1)...]) }\n",
    "\n",
    "let trainPercentage:Float = 0.8\n",
    "let numTrainRecords = Int(ceil(Float(numRecords) * trainPercentage))\n",
    "let numTestRecords = numRecords - numTrainRecords\n",
    "\n",
    "let trainFeatures = Array(dataFeatures[0..<numTrainRecords])\n",
    "let trainLabels = Array(dataLabels[0..<numTrainRecords])\n",
    "let testFeatures = Array(dataFeatures[numTrainRecords...])\n",
    "let testLabels = Array(dataLabels[numTrainRecords...])\n",
    "\n",
    "print(\"Training shapes [\\(trainFeatures.count) \\(trainFeatures[0].count)] [\\(trainLabels.count) \\(trainLabels[0].count)]\")\n",
    "print(\"Testing shapes  [\\(testFeatures.count) \\(testFeatures[0].count)] [\\(testLabels.count) \\(testLabels[0].count)]\")\n",
    "\n",
    "let xAllTrain = Array(trainFeatures.joined())\n",
    "let yAllTrain = Array(trainLabels.joined())\n",
    "let xAllTest = Array(testFeatures.joined())\n",
    "let yAllTest = Array(testLabels.joined())\n",
    "\n",
    "let XTrainDeNorm = Tensor<Float>(xAllTrain).reshaped(to: TensorShape([numTrainRecords, numColumns-1]))\n",
    "let YTrain = Tensor<Float>(yAllTrain).reshaped(to: TensorShape([numTrainRecords, 1]))\n",
    "let XTestDeNorm = Tensor<Float>(xAllTest).reshaped(to: TensorShape([numTestRecords, numColumns-1]))\n",
    "let YTest = Tensor<Float>(yAllTest).reshaped(to: TensorShape([numTestRecords, 1]))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Normalize"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[  2.0137098,   14.197531,    9.523555, 0.086419754,  0.53213036,   6.3311296,    64.47929,\r\n",
      "    4.1678762,    6.832099,   353.68396,    18.03163,   379.84735,   11.394517]] [[ 6.5076075,  25.258776,   6.534038, 0.28098345, 0.11449408,  0.7311985,  29.000755,  2.1797554,\r\n",
      "    6.544165,  132.14561,  2.2173452,  40.494495,   6.852825]]\r\n"
     ]
    }
   ],
   "source": [
    "let mean = XTrainDeNorm.mean(alongAxes: 0)\n",
    "let std = XTrainDeNorm.standardDeviation(alongAxes: 0)\n",
    "\n",
    "print(mean, std)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "let XTrain = (XTrainDeNorm - mean)/std\n",
    "let XTest = (XTestDeNorm - mean)/std"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[405, 13] [405, 1] [101, 13] [101, 1]\r\n"
     ]
    }
   ],
   "source": [
    "print(XTrain.shape, YTrain.shape, XTest.shape, YTest.shape)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Model"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "colab": {},
    "colab_type": "code",
    "id": "HDJZCCgqohIC"
   },
   "outputs": [],
   "source": [
    "struct RegressionModel: Layer {\n",
    "    var layer1 = Dense<Float>(inputSize: 13, outputSize: 64, activation: relu)\n",
    "    var layer2 = Dense<Float>(inputSize: 64, outputSize: 32, activation: relu)\n",
    "    var layer3 = Dense<Float>(inputSize: 32, outputSize: 1)\n",
    "    \n",
    "    @differentiable\n",
    "    func callAsFunction(_ input: Tensor<Float>) -> Tensor<Float> {\n",
    "        return input.sequenced(through: layer1, layer2, layer3)\n",
    "    }\n",
    "}\n",
    "\n",
    "var model = RegressionModel()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Training"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {
    "colab": {},
    "colab_type": "code",
    "id": "JK0Vj7bSohIF"
   },
   "outputs": [],
   "source": [
    "let optimizer = RMSProp(for: model, learningRate: 0.001)\n",
    "Context.local.learningPhase = .training"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {
    "colab": {},
    "colab_type": "code",
    "id": "gY8C7yHJohIH"
   },
   "outputs": [],
   "source": [
    "let epochCount = 500\n",
    "let batchSize = 32\n",
    "let numberOfBatch = Int(ceil(Double(numTrainRecords) / Double(batchSize)))\n",
    "let shuffle = true\n",
    "\n",
    "func mae(predictions: Tensor<Float>, truths: Tensor<Float>) -> Float {\n",
    "    return abs(Tensor<Float>(predictions - truths)).mean().scalarized()\n",
    "}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 203
    },
    "colab_type": "code",
    "id": "L9bU9HsdohIK",
    "outputId": "692b81c5-3286-4e7c-9246-eb56e6a3eaee"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 1: MSE: 589.81085, MAE: 21.91811\n",
      "Epoch 2: MSE: 532.30084, MAE: 20.598415\n",
      "Epoch 3: MSE: 471.52426, MAE: 19.115623\n",
      "Epoch 4: MSE: 406.53738, MAE: 17.479641\n",
      "Epoch 5: MSE: 338.0967, MAE: 15.640751\n",
      "Epoch 6: MSE: 273.65936, MAE: 13.59707\n",
      "Epoch 7: MSE: 214.2916, MAE: 11.672209\n",
      "Epoch 8: MSE: 167.4195, MAE: 9.808268\n",
      "Epoch 9: MSE: 131.0001, MAE: 8.390486\n",
      "Epoch 10: MSE: 103.84559, MAE: 7.331494\n",
      "Epoch 11: MSE: 84.44268, MAE: 6.512589\n",
      "Epoch 12: MSE: 69.91607, MAE: 5.7860866\n",
      "Epoch 13: MSE: 57.865364, MAE: 5.234492\n",
      "Epoch 14: MSE: 48.205647, MAE: 4.7263517\n",
      "Epoch 15: MSE: 41.01215, MAE: 4.35292\n",
      "Epoch 16: MSE: 35.789993, MAE: 3.9689064\n",
      "Epoch 17: MSE: 32.554733, MAE: 3.7550542\n",
      "Epoch 18: MSE: 29.312397, MAE: 3.5553021\n",
      "Epoch 19: MSE: 27.672157, MAE: 3.4326134\n",
      "Epoch 20: MSE: 26.412117, MAE: 3.3594458\n",
      "Epoch 21: MSE: 24.803968, MAE: 3.229053\n",
      "Epoch 22: MSE: 23.748573, MAE: 3.1771557\n",
      "Epoch 23: MSE: 22.921827, MAE: 3.097651\n",
      "Epoch 24: MSE: 21.684204, MAE: 2.9909055\n",
      "Epoch 25: MSE: 21.041624, MAE: 2.910099\n",
      "Epoch 26: MSE: 19.760925, MAE: 2.8809714\n",
      "Epoch 27: MSE: 19.396069, MAE: 2.8177683\n",
      "Epoch 28: MSE: 18.786467, MAE: 2.7539084\n",
      "Epoch 29: MSE: 18.128899, MAE: 2.6866605\n",
      "Epoch 30: MSE: 17.461235, MAE: 2.6489906\n",
      "Epoch 31: MSE: 16.901052, MAE: 2.6063385\n",
      "Epoch 32: MSE: 16.549177, MAE: 2.5840979\n",
      "Epoch 33: MSE: 15.76065, MAE: 2.549324\n",
      "Epoch 34: MSE: 15.497344, MAE: 2.4824371\n",
      "Epoch 35: MSE: 15.169617, MAE: 2.4644916\n",
      "Epoch 36: MSE: 14.78323, MAE: 2.398743\n",
      "Epoch 37: MSE: 14.291349, MAE: 2.396502\n",
      "Epoch 38: MSE: 13.671173, MAE: 2.3250341\n",
      "Epoch 39: MSE: 13.688906, MAE: 2.3183732\n",
      "Epoch 40: MSE: 13.554062, MAE: 2.284722\n",
      "Epoch 41: MSE: 13.232308, MAE: 2.2655487\n",
      "Epoch 42: MSE: 12.835081, MAE: 2.2654333\n",
      "Epoch 43: MSE: 12.752716, MAE: 2.2182157\n",
      "Epoch 44: MSE: 12.404636, MAE: 2.1975446\n",
      "Epoch 45: MSE: 12.245193, MAE: 2.1555061\n",
      "Epoch 46: MSE: 12.079885, MAE: 2.1671462\n",
      "Epoch 47: MSE: 11.809493, MAE: 2.1463442\n",
      "Epoch 48: MSE: 11.7356825, MAE: 2.1169257\n",
      "Epoch 49: MSE: 11.644128, MAE: 2.0976706\n",
      "Epoch 50: MSE: 11.543064, MAE: 2.1165233\n",
      "Epoch 51: MSE: 11.147414, MAE: 2.0847254\n",
      "Epoch 52: MSE: 10.842101, MAE: 2.0753217\n",
      "Epoch 53: MSE: 10.930205, MAE: 2.0493217\n",
      "Epoch 54: MSE: 10.740899, MAE: 2.0482364\n",
      "Epoch 55: MSE: 10.826447, MAE: 2.043596\n",
      "Epoch 56: MSE: 10.640559, MAE: 2.0419466\n",
      "Epoch 57: MSE: 10.382259, MAE: 2.0289145\n",
      "Epoch 58: MSE: 10.462902, MAE: 2.0345495\n",
      "Epoch 59: MSE: 10.185553, MAE: 2.0086\n",
      "Epoch 60: MSE: 10.065757, MAE: 1.9828992\n",
      "Epoch 61: MSE: 10.055776, MAE: 1.9697522\n",
      "Epoch 62: MSE: 10.085622, MAE: 1.9894655\n",
      "Epoch 63: MSE: 9.710839, MAE: 1.9841069\n",
      "Epoch 64: MSE: 9.889421, MAE: 1.970368\n",
      "Epoch 65: MSE: 9.733693, MAE: 1.9653614\n",
      "Epoch 66: MSE: 9.791693, MAE: 1.9652082\n",
      "Epoch 67: MSE: 9.748527, MAE: 1.958103\n",
      "Epoch 68: MSE: 9.235938, MAE: 1.9234084\n",
      "Epoch 69: MSE: 9.487232, MAE: 1.9456024\n",
      "Epoch 70: MSE: 9.453613, MAE: 1.9308412\n",
      "Epoch 71: MSE: 9.108028, MAE: 1.9154421\n",
      "Epoch 72: MSE: 9.180658, MAE: 1.916633\n",
      "Epoch 73: MSE: 9.124501, MAE: 1.9130988\n",
      "Epoch 74: MSE: 8.738622, MAE: 1.8825616\n",
      "Epoch 75: MSE: 9.056433, MAE: 1.8876277\n",
      "Epoch 76: MSE: 8.951967, MAE: 1.8917959\n",
      "Epoch 77: MSE: 8.581391, MAE: 1.8677094\n",
      "Epoch 78: MSE: 8.873224, MAE: 1.8698415\n",
      "Epoch 79: MSE: 8.753576, MAE: 1.8569235\n",
      "Epoch 80: MSE: 8.660326, MAE: 1.8597316\n",
      "Epoch 81: MSE: 8.3450775, MAE: 1.831681\n",
      "Epoch 82: MSE: 8.5515785, MAE: 1.8347541\n",
      "Epoch 83: MSE: 8.434888, MAE: 1.8358555\n",
      "Epoch 84: MSE: 8.08941, MAE: 1.8183513\n",
      "Epoch 85: MSE: 8.397177, MAE: 1.8223364\n",
      "Epoch 86: MSE: 8.21532, MAE: 1.823146\n",
      "Epoch 87: MSE: 8.220864, MAE: 1.8093677\n",
      "Epoch 88: MSE: 8.109564, MAE: 1.8032602\n",
      "Epoch 89: MSE: 8.000088, MAE: 1.7810324\n",
      "Epoch 90: MSE: 8.0297985, MAE: 1.780388\n",
      "Epoch 91: MSE: 7.733131, MAE: 1.7533588\n",
      "Epoch 92: MSE: 7.930295, MAE: 1.7778276\n",
      "Epoch 93: MSE: 7.7988005, MAE: 1.7657365\n",
      "Epoch 94: MSE: 7.7369967, MAE: 1.7475755\n",
      "Epoch 95: MSE: 7.5493045, MAE: 1.7450949\n",
      "Epoch 96: MSE: 7.4732723, MAE: 1.7354834\n",
      "Epoch 97: MSE: 7.6036115, MAE: 1.7411425\n",
      "Epoch 98: MSE: 7.2972283, MAE: 1.7315797\n",
      "Epoch 99: MSE: 7.5090733, MAE: 1.7311959\n",
      "Epoch 100: MSE: 7.3509035, MAE: 1.7376298\n",
      "Epoch 101: MSE: 7.25657, MAE: 1.7127762\n",
      "Epoch 102: MSE: 7.130936, MAE: 1.6969936\n",
      "Epoch 103: MSE: 7.334847, MAE: 1.7106646\n",
      "Epoch 104: MSE: 7.1022387, MAE: 1.6889812\n",
      "Epoch 105: MSE: 7.2414403, MAE: 1.7098918\n",
      "Epoch 106: MSE: 7.076371, MAE: 1.6895245\n",
      "Epoch 107: MSE: 7.0082784, MAE: 1.6887906\n",
      "Epoch 108: MSE: 6.7245383, MAE: 1.6602345\n",
      "Epoch 109: MSE: 7.051311, MAE: 1.6910678\n",
      "Epoch 110: MSE: 6.8815985, MAE: 1.6623764\n",
      "Epoch 111: MSE: 6.8551416, MAE: 1.6601461\n",
      "Epoch 112: MSE: 6.7441235, MAE: 1.6621953\n",
      "Epoch 113: MSE: 6.735852, MAE: 1.6648134\n",
      "Epoch 114: MSE: 6.7170663, MAE: 1.6423061\n",
      "Epoch 115: MSE: 6.661149, MAE: 1.6531419\n",
      "Epoch 116: MSE: 6.564305, MAE: 1.6461768\n",
      "Epoch 117: MSE: 6.6751566, MAE: 1.6402758\n",
      "Epoch 118: MSE: 6.457548, MAE: 1.6373556\n",
      "Epoch 119: MSE: 6.4274006, MAE: 1.6172887\n",
      "Epoch 120: MSE: 6.6281424, MAE: 1.6312234\n",
      "Epoch 121: MSE: 6.179211, MAE: 1.6142405\n",
      "Epoch 122: MSE: 6.4618077, MAE: 1.6192601\n",
      "Epoch 123: MSE: 6.093167, MAE: 1.5991756\n",
      "Epoch 124: MSE: 6.19737, MAE: 1.5874971\n",
      "Epoch 125: MSE: 6.1382327, MAE: 1.5888537\n",
      "Epoch 126: MSE: 5.997403, MAE: 1.5884334\n",
      "Epoch 127: MSE: 6.247878, MAE: 1.610852\n",
      "Epoch 128: MSE: 5.907939, MAE: 1.5659583\n",
      "Epoch 129: MSE: 6.0429206, MAE: 1.5885079\n",
      "Epoch 130: MSE: 6.028149, MAE: 1.5732229\n",
      "Epoch 131: MSE: 6.079569, MAE: 1.5827458\n",
      "Epoch 132: MSE: 6.0107303, MAE: 1.5899823\n",
      "Epoch 133: MSE: 5.8128057, MAE: 1.5551091\n",
      "Epoch 134: MSE: 5.819005, MAE: 1.5495776\n",
      "Epoch 135: MSE: 6.0531335, MAE: 1.5678147\n",
      "Epoch 136: MSE: 5.5506234, MAE: 1.5423739\n",
      "Epoch 137: MSE: 5.8253074, MAE: 1.5584406\n",
      "Epoch 138: MSE: 5.882759, MAE: 1.5546995\n",
      "Epoch 139: MSE: 5.5901117, MAE: 1.5267541\n",
      "Epoch 140: MSE: 5.615331, MAE: 1.5358895\n",
      "Epoch 141: MSE: 5.8182244, MAE: 1.528775\n",
      "Epoch 142: MSE: 5.4756656, MAE: 1.5196182\n",
      "Epoch 143: MSE: 5.435301, MAE: 1.514249\n",
      "Epoch 144: MSE: 5.5314703, MAE: 1.5208563\n",
      "Epoch 145: MSE: 5.353859, MAE: 1.4984665\n",
      "Epoch 146: MSE: 5.400021, MAE: 1.5012537\n",
      "Epoch 147: MSE: 5.647088, MAE: 1.5122678\n",
      "Epoch 148: MSE: 5.513718, MAE: 1.5143323\n",
      "Epoch 149: MSE: 5.392993, MAE: 1.4979551\n",
      "Epoch 150: MSE: 5.3553524, MAE: 1.5057945\n",
      "Epoch 151: MSE: 5.3431673, MAE: 1.5007676\n",
      "Epoch 152: MSE: 5.173737, MAE: 1.4726472\n",
      "Epoch 153: MSE: 5.257454, MAE: 1.5156085\n",
      "Epoch 154: MSE: 5.241516, MAE: 1.4922224\n",
      "Epoch 155: MSE: 5.0574703, MAE: 1.4773705\n",
      "Epoch 156: MSE: 5.0900493, MAE: 1.4815559\n",
      "Epoch 157: MSE: 5.1571913, MAE: 1.464874\n",
      "Epoch 158: MSE: 5.243068, MAE: 1.4659964\n",
      "Epoch 159: MSE: 4.937887, MAE: 1.4483637\n",
      "Epoch 160: MSE: 5.018364, MAE: 1.4742631\n",
      "Epoch 161: MSE: 5.1410546, MAE: 1.4795799\n",
      "Epoch 162: MSE: 4.850924, MAE: 1.4380301\n",
      "Epoch 163: MSE: 4.837398, MAE: 1.4398632\n",
      "Epoch 164: MSE: 4.9282837, MAE: 1.4584903\n",
      "Epoch 165: MSE: 4.686401, MAE: 1.4291785\n",
      "Epoch 166: MSE: 4.946278, MAE: 1.425443\n",
      "Epoch 167: MSE: 4.9374013, MAE: 1.4525948\n",
      "Epoch 168: MSE: 4.7971783, MAE: 1.4167565\n",
      "Epoch 169: MSE: 4.586773, MAE: 1.411474\n",
      "Epoch 170: MSE: 4.9193883, MAE: 1.425625\n",
      "Epoch 171: MSE: 4.6808963, MAE: 1.4196427\n",
      "Epoch 172: MSE: 4.5323863, MAE: 1.4031252\n",
      "Epoch 173: MSE: 4.8022037, MAE: 1.4406126\n",
      "Epoch 174: MSE: 4.6930447, MAE: 1.4287969\n",
      "Epoch 175: MSE: 4.6165743, MAE: 1.4033195\n",
      "Epoch 176: MSE: 4.550069, MAE: 1.3838618\n",
      "Epoch 177: MSE: 4.7522135, MAE: 1.4371235\n",
      "Epoch 178: MSE: 4.289315, MAE: 1.3840936\n",
      "Epoch 179: MSE: 4.699859, MAE: 1.4273016\n",
      "Epoch 180: MSE: 4.5391665, MAE: 1.3870639\n",
      "Epoch 181: MSE: 4.3546214, MAE: 1.3678705\n",
      "Epoch 182: MSE: 4.6913896, MAE: 1.3972785\n",
      "Epoch 183: MSE: 4.4869237, MAE: 1.3838164\n",
      "Epoch 184: MSE: 4.536037, MAE: 1.3883011\n",
      "Epoch 185: MSE: 4.39192, MAE: 1.3843417\n",
      "Epoch 186: MSE: 4.2337084, MAE: 1.3783457\n",
      "Epoch 187: MSE: 4.4344335, MAE: 1.3953037\n",
      "Epoch 188: MSE: 4.473202, MAE: 1.3858662\n",
      "Epoch 189: MSE: 4.236516, MAE: 1.3414012\n",
      "Epoch 190: MSE: 4.491003, MAE: 1.41521\n",
      "Epoch 191: MSE: 4.203603, MAE: 1.365204\n",
      "Epoch 192: MSE: 4.356366, MAE: 1.3740995\n",
      "Epoch 193: MSE: 4.163772, MAE: 1.3623401\n",
      "Epoch 194: MSE: 4.14873, MAE: 1.3777318\n",
      "Epoch 195: MSE: 4.2501254, MAE: 1.359251\n",
      "Epoch 196: MSE: 4.2647986, MAE: 1.339171\n",
      "Epoch 197: MSE: 4.051929, MAE: 1.3476849\n",
      "Epoch 198: MSE: 4.0902843, MAE: 1.3525505\n",
      "Epoch 199: MSE: 4.142464, MAE: 1.3297094\n",
      "Epoch 200: MSE: 4.000003, MAE: 1.3288658\n",
      "Epoch 201: MSE: 4.018126, MAE: 1.331785\n",
      "Epoch 202: MSE: 3.9036982, MAE: 1.3347642\n",
      "Epoch 203: MSE: 4.3332376, MAE: 1.3189696\n",
      "Epoch 204: MSE: 4.0308437, MAE: 1.3264217\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 205: MSE: 3.8929899, MAE: 1.3233553\n",
      "Epoch 206: MSE: 3.9347196, MAE: 1.3088499\n",
      "Epoch 207: MSE: 4.1642003, MAE: 1.3574431\n",
      "Epoch 208: MSE: 3.9191463, MAE: 1.3176068\n",
      "Epoch 209: MSE: 4.0800037, MAE: 1.3158011\n",
      "Epoch 210: MSE: 3.86485, MAE: 1.2927513\n",
      "Epoch 211: MSE: 3.7487135, MAE: 1.2933971\n",
      "Epoch 212: MSE: 4.255821, MAE: 1.3012805\n",
      "Epoch 213: MSE: 3.6888735, MAE: 1.2751573\n",
      "Epoch 214: MSE: 4.1169477, MAE: 1.3376248\n",
      "Epoch 215: MSE: 3.8661308, MAE: 1.301401\n",
      "Epoch 216: MSE: 3.880018, MAE: 1.3036292\n",
      "Epoch 217: MSE: 3.762938, MAE: 1.2912028\n",
      "Epoch 218: MSE: 3.7680612, MAE: 1.273327\n",
      "Epoch 219: MSE: 3.7489762, MAE: 1.2884958\n",
      "Epoch 220: MSE: 4.0362253, MAE: 1.3122103\n",
      "Epoch 221: MSE: 3.8192155, MAE: 1.3059095\n",
      "Epoch 222: MSE: 3.645543, MAE: 1.253865\n",
      "Epoch 223: MSE: 3.8001466, MAE: 1.2974814\n",
      "Epoch 224: MSE: 3.7164667, MAE: 1.2707146\n",
      "Epoch 225: MSE: 3.8923404, MAE: 1.2865106\n",
      "Epoch 226: MSE: 3.6474395, MAE: 1.2795918\n",
      "Epoch 227: MSE: 3.8348398, MAE: 1.2878511\n",
      "Epoch 228: MSE: 3.6273088, MAE: 1.2543614\n",
      "Epoch 229: MSE: 3.6449301, MAE: 1.268086\n",
      "Epoch 230: MSE: 3.817094, MAE: 1.2825954\n",
      "Epoch 231: MSE: 3.6310854, MAE: 1.2654669\n",
      "Epoch 232: MSE: 3.589972, MAE: 1.2513201\n",
      "Epoch 233: MSE: 3.610741, MAE: 1.2812613\n",
      "Epoch 234: MSE: 3.7045047, MAE: 1.2781762\n",
      "Epoch 235: MSE: 3.625224, MAE: 1.2758509\n",
      "Epoch 236: MSE: 3.5782943, MAE: 1.270186\n",
      "Epoch 237: MSE: 3.5428925, MAE: 1.2668879\n",
      "Epoch 238: MSE: 3.7454364, MAE: 1.2857457\n",
      "Epoch 239: MSE: 3.5274656, MAE: 1.2411671\n",
      "Epoch 240: MSE: 3.6893032, MAE: 1.2864732\n",
      "Epoch 241: MSE: 3.4276288, MAE: 1.2625606\n",
      "Epoch 242: MSE: 3.5917025, MAE: 1.2847259\n",
      "Epoch 243: MSE: 3.5024111, MAE: 1.2679195\n",
      "Epoch 244: MSE: 3.5030901, MAE: 1.2520595\n",
      "Epoch 245: MSE: 3.6467097, MAE: 1.2530286\n",
      "Epoch 246: MSE: 3.3734014, MAE: 1.2300539\n",
      "Epoch 247: MSE: 3.3617423, MAE: 1.2314922\n",
      "Epoch 248: MSE: 3.5385408, MAE: 1.2854581\n",
      "Epoch 249: MSE: 3.5795596, MAE: 1.2319484\n",
      "Epoch 250: MSE: 3.3234787, MAE: 1.2129159\n",
      "Epoch 251: MSE: 3.4682846, MAE: 1.2559892\n",
      "Epoch 252: MSE: 3.293626, MAE: 1.2325929\n",
      "Epoch 253: MSE: 3.4128096, MAE: 1.2226533\n",
      "Epoch 254: MSE: 3.549589, MAE: 1.2672055\n",
      "Epoch 255: MSE: 3.3606288, MAE: 1.2127205\n",
      "Epoch 256: MSE: 3.2347934, MAE: 1.2240297\n",
      "Epoch 257: MSE: 3.330854, MAE: 1.2131871\n",
      "Epoch 258: MSE: 3.427494, MAE: 1.2036959\n",
      "Epoch 259: MSE: 3.3936949, MAE: 1.2213926\n",
      "Epoch 260: MSE: 3.476309, MAE: 1.2502052\n",
      "Epoch 261: MSE: 3.1902735, MAE: 1.208183\n",
      "Epoch 262: MSE: 3.1988375, MAE: 1.2363986\n",
      "Epoch 263: MSE: 3.4616847, MAE: 1.2281272\n",
      "Epoch 264: MSE: 3.3946662, MAE: 1.2223201\n",
      "Epoch 265: MSE: 3.1256843, MAE: 1.1857543\n",
      "Epoch 266: MSE: 3.3464406, MAE: 1.2636683\n",
      "Epoch 267: MSE: 3.2036276, MAE: 1.2274064\n",
      "Epoch 268: MSE: 3.1379166, MAE: 1.1820017\n",
      "Epoch 269: MSE: 3.37684, MAE: 1.222235\n",
      "Epoch 270: MSE: 3.1640558, MAE: 1.1671157\n",
      "Epoch 271: MSE: 3.1062188, MAE: 1.2317761\n",
      "Epoch 272: MSE: 3.4423423, MAE: 1.208879\n",
      "Epoch 273: MSE: 3.1185033, MAE: 1.1946857\n",
      "Epoch 274: MSE: 3.4118445, MAE: 1.2377924\n",
      "Epoch 275: MSE: 3.0270371, MAE: 1.1660181\n",
      "Epoch 276: MSE: 3.137549, MAE: 1.2011237\n",
      "Epoch 277: MSE: 3.503468, MAE: 1.2298807\n",
      "Epoch 278: MSE: 2.9682527, MAE: 1.1259118\n",
      "Epoch 279: MSE: 3.2248917, MAE: 1.2073141\n",
      "Epoch 280: MSE: 3.2163122, MAE: 1.181539\n",
      "Epoch 281: MSE: 3.3208487, MAE: 1.2277516\n",
      "Epoch 282: MSE: 2.9884653, MAE: 1.1596887\n",
      "Epoch 283: MSE: 3.3328347, MAE: 1.2197978\n",
      "Epoch 284: MSE: 2.9619417, MAE: 1.1484119\n",
      "Epoch 285: MSE: 3.1140375, MAE: 1.1844802\n",
      "Epoch 286: MSE: 3.3079567, MAE: 1.2094522\n",
      "Epoch 287: MSE: 3.1728475, MAE: 1.1828554\n",
      "Epoch 288: MSE: 2.9957328, MAE: 1.159734\n",
      "Epoch 289: MSE: 2.9394622, MAE: 1.1879592\n",
      "Epoch 290: MSE: 3.044975, MAE: 1.1808659\n",
      "Epoch 291: MSE: 2.8570046, MAE: 1.1611817\n",
      "Epoch 292: MSE: 3.2578845, MAE: 1.2177652\n",
      "Epoch 293: MSE: 2.993135, MAE: 1.1593585\n",
      "Epoch 294: MSE: 2.9262834, MAE: 1.1714475\n",
      "Epoch 295: MSE: 3.3446703, MAE: 1.2069745\n",
      "Epoch 296: MSE: 2.9768395, MAE: 1.1522962\n",
      "Epoch 297: MSE: 3.0119307, MAE: 1.2082857\n",
      "Epoch 298: MSE: 2.9649415, MAE: 1.1614559\n",
      "Epoch 299: MSE: 3.009069, MAE: 1.1515515\n",
      "Epoch 300: MSE: 3.1870794, MAE: 1.1612444\n",
      "Epoch 301: MSE: 2.9105482, MAE: 1.1534879\n",
      "Epoch 302: MSE: 2.9910045, MAE: 1.2084668\n",
      "Epoch 303: MSE: 2.9263253, MAE: 1.1867915\n",
      "Epoch 304: MSE: 2.7955332, MAE: 1.1632937\n",
      "Epoch 305: MSE: 3.005073, MAE: 1.2306089\n",
      "Epoch 306: MSE: 2.9862761, MAE: 1.160806\n",
      "Epoch 307: MSE: 3.0631373, MAE: 1.1722548\n",
      "Epoch 308: MSE: 2.9621625, MAE: 1.1643844\n",
      "Epoch 309: MSE: 2.8510756, MAE: 1.1223397\n",
      "Epoch 310: MSE: 2.9205039, MAE: 1.2037714\n",
      "Epoch 311: MSE: 2.9522285, MAE: 1.1252961\n",
      "Epoch 312: MSE: 2.8911543, MAE: 1.2041179\n",
      "Epoch 313: MSE: 2.9641798, MAE: 1.1557562\n",
      "Epoch 314: MSE: 2.8175063, MAE: 1.1333159\n",
      "Epoch 315: MSE: 2.96611, MAE: 1.1945647\n",
      "Epoch 316: MSE: 2.869052, MAE: 1.1353674\n",
      "Epoch 317: MSE: 2.8391726, MAE: 1.1753856\n",
      "Epoch 318: MSE: 2.803995, MAE: 1.1781514\n",
      "Epoch 319: MSE: 2.8045232, MAE: 1.1392077\n",
      "Epoch 320: MSE: 2.958197, MAE: 1.1421115\n",
      "Epoch 321: MSE: 2.9053493, MAE: 1.1487274\n",
      "Epoch 322: MSE: 2.7274365, MAE: 1.1608353\n",
      "Epoch 323: MSE: 2.9592776, MAE: 1.1357251\n",
      "Epoch 324: MSE: 2.705794, MAE: 1.127325\n",
      "Epoch 325: MSE: 2.7725396, MAE: 1.1827326\n",
      "Epoch 326: MSE: 2.9014459, MAE: 1.1535631\n",
      "Epoch 327: MSE: 3.0257864, MAE: 1.1811242\n",
      "Epoch 328: MSE: 2.7045348, MAE: 1.0702443\n",
      "Epoch 329: MSE: 2.683339, MAE: 1.1702514\n",
      "Epoch 330: MSE: 2.7513757, MAE: 1.1425624\n",
      "Epoch 331: MSE: 2.7002249, MAE: 1.170956\n",
      "Epoch 332: MSE: 2.6890752, MAE: 1.1324283\n",
      "Epoch 333: MSE: 2.6891646, MAE: 1.1635509\n",
      "Epoch 334: MSE: 2.7579684, MAE: 1.1425265\n",
      "Epoch 335: MSE: 3.1555192, MAE: 1.1460128\n",
      "Epoch 336: MSE: 2.6440823, MAE: 1.0733235\n",
      "Epoch 337: MSE: 2.8800838, MAE: 1.1738443\n",
      "Epoch 338: MSE: 2.6639264, MAE: 1.1005164\n",
      "Epoch 339: MSE: 2.6922784, MAE: 1.131743\n",
      "Epoch 340: MSE: 2.8022192, MAE: 1.1326873\n",
      "Epoch 341: MSE: 2.8153481, MAE: 1.1404245\n",
      "Epoch 342: MSE: 2.475989, MAE: 1.1312528\n",
      "Epoch 343: MSE: 2.8567178, MAE: 1.1614887\n",
      "Epoch 344: MSE: 2.6157026, MAE: 1.1238568\n",
      "Epoch 345: MSE: 2.8369315, MAE: 1.1608388\n",
      "Epoch 346: MSE: 2.676248, MAE: 1.0771918\n",
      "Epoch 347: MSE: 2.75325, MAE: 1.1318908\n",
      "Epoch 348: MSE: 2.6523004, MAE: 1.10938\n",
      "Epoch 349: MSE: 2.829371, MAE: 1.1787009\n",
      "Epoch 350: MSE: 2.7445006, MAE: 1.1091416\n",
      "Epoch 351: MSE: 2.4623895, MAE: 1.0584674\n",
      "Epoch 352: MSE: 2.5776434, MAE: 1.1421064\n",
      "Epoch 353: MSE: 2.666241, MAE: 1.1467296\n",
      "Epoch 354: MSE: 2.9422078, MAE: 1.1201148\n",
      "Epoch 355: MSE: 2.6599796, MAE: 1.0913457\n",
      "Epoch 356: MSE: 2.4973502, MAE: 1.1195817\n",
      "Epoch 357: MSE: 2.6889968, MAE: 1.1672249\n",
      "Epoch 358: MSE: 2.8015504, MAE: 1.1123278\n",
      "Epoch 359: MSE: 2.4957135, MAE: 1.0771706\n",
      "Epoch 360: MSE: 2.6268306, MAE: 1.1313058\n",
      "Epoch 361: MSE: 2.6986809, MAE: 1.1284416\n",
      "Epoch 362: MSE: 2.6529794, MAE: 1.1254023\n",
      "Epoch 363: MSE: 2.5454037, MAE: 1.0559514\n",
      "Epoch 364: MSE: 2.550425, MAE: 1.1130948\n",
      "Epoch 365: MSE: 2.7510195, MAE: 1.1153398\n",
      "Epoch 366: MSE: 2.6520832, MAE: 1.1235188\n",
      "Epoch 367: MSE: 2.5257113, MAE: 1.1254058\n",
      "Epoch 368: MSE: 2.6209555, MAE: 1.1428496\n",
      "Epoch 369: MSE: 2.6743352, MAE: 1.0900136\n",
      "Epoch 370: MSE: 2.382924, MAE: 1.0877872\n",
      "Epoch 371: MSE: 2.9502776, MAE: 1.1378942\n",
      "Epoch 372: MSE: 2.54638, MAE: 1.0915334\n",
      "Epoch 373: MSE: 2.343137, MAE: 1.1142111\n",
      "Epoch 374: MSE: 2.762147, MAE: 1.118298\n",
      "Epoch 375: MSE: 2.528516, MAE: 1.0731782\n",
      "Epoch 376: MSE: 2.4352322, MAE: 1.0887706\n",
      "Epoch 377: MSE: 2.6459455, MAE: 1.118259\n",
      "Epoch 378: MSE: 2.6631448, MAE: 1.0730858\n",
      "Epoch 379: MSE: 2.622658, MAE: 1.0885262\n",
      "Epoch 380: MSE: 2.5327656, MAE: 1.0896474\n",
      "Epoch 381: MSE: 2.527712, MAE: 1.0969175\n",
      "Epoch 382: MSE: 2.3539135, MAE: 1.0776412\n",
      "Epoch 383: MSE: 2.526589, MAE: 1.052684\n",
      "Epoch 384: MSE: 2.592278, MAE: 1.1760566\n",
      "Epoch 385: MSE: 2.4195268, MAE: 1.0638628\n",
      "Epoch 386: MSE: 2.5464034, MAE: 1.1063756\n",
      "Epoch 387: MSE: 2.4655762, MAE: 1.0834982\n",
      "Epoch 388: MSE: 2.3123813, MAE: 1.0171912\n",
      "Epoch 389: MSE: 2.5785508, MAE: 1.0995286\n",
      "Epoch 390: MSE: 2.5309718, MAE: 1.0812466\n",
      "Epoch 391: MSE: 2.4930532, MAE: 1.0637478\n",
      "Epoch 392: MSE: 2.3782427, MAE: 1.0692033\n",
      "Epoch 393: MSE: 2.201421, MAE: 1.0116502\n",
      "Epoch 394: MSE: 2.7669132, MAE: 1.2005274\n",
      "Epoch 395: MSE: 2.5637577, MAE: 1.048132\n",
      "Epoch 396: MSE: 2.2512758, MAE: 1.0173551\n",
      "Epoch 397: MSE: 2.322854, MAE: 1.0330173\n",
      "Epoch 398: MSE: 2.6262636, MAE: 1.0946416\n",
      "Epoch 399: MSE: 2.222434, MAE: 1.0432267\n",
      "Epoch 400: MSE: 2.4238696, MAE: 1.0524164\n",
      "Epoch 401: MSE: 2.4150426, MAE: 1.076443\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 402: MSE: 2.5191193, MAE: 1.0958669\n",
      "Epoch 403: MSE: 2.3870103, MAE: 1.064272\n",
      "Epoch 404: MSE: 2.6042123, MAE: 1.1122155\n",
      "Epoch 405: MSE: 2.2502027, MAE: 1.0423396\n",
      "Epoch 406: MSE: 2.2356317, MAE: 1.0436115\n",
      "Epoch 407: MSE: 2.546919, MAE: 1.1543307\n",
      "Epoch 408: MSE: 2.2689524, MAE: 1.0468328\n",
      "Epoch 409: MSE: 2.4096115, MAE: 1.1191856\n",
      "Epoch 410: MSE: 2.4195154, MAE: 1.0729276\n",
      "Epoch 411: MSE: 2.2556474, MAE: 1.0638112\n",
      "Epoch 412: MSE: 2.6347125, MAE: 1.0511119\n",
      "Epoch 413: MSE: 2.2540889, MAE: 1.0044751\n",
      "Epoch 414: MSE: 2.297465, MAE: 1.0993241\n",
      "Epoch 415: MSE: 2.5899913, MAE: 1.1363679\n",
      "Epoch 416: MSE: 2.349672, MAE: 1.0532255\n",
      "Epoch 417: MSE: 2.2123332, MAE: 1.0402236\n",
      "Epoch 418: MSE: 2.468155, MAE: 1.0614207\n",
      "Epoch 419: MSE: 2.2284586, MAE: 0.99371296\n",
      "Epoch 420: MSE: 2.4191208, MAE: 1.1322768\n",
      "Epoch 421: MSE: 2.3195207, MAE: 1.0351545\n",
      "Epoch 422: MSE: 2.3122172, MAE: 1.1503565\n",
      "Epoch 423: MSE: 2.1746047, MAE: 1.0312278\n",
      "Epoch 424: MSE: 2.2582936, MAE: 1.0885746\n",
      "Epoch 425: MSE: 2.1674268, MAE: 1.0763129\n",
      "Epoch 426: MSE: 2.5185018, MAE: 1.1177976\n",
      "Epoch 427: MSE: 2.404872, MAE: 1.0370107\n",
      "Epoch 428: MSE: 2.4060767, MAE: 1.0395281\n",
      "Epoch 429: MSE: 2.227814, MAE: 1.0513707\n",
      "Epoch 430: MSE: 2.4386938, MAE: 1.0777442\n",
      "Epoch 431: MSE: 2.3429034, MAE: 1.0897142\n",
      "Epoch 432: MSE: 2.2651699, MAE: 1.0135316\n",
      "Epoch 433: MSE: 2.1880314, MAE: 1.0520008\n",
      "Epoch 434: MSE: 2.4479327, MAE: 1.157202\n",
      "Epoch 435: MSE: 2.1240847, MAE: 0.9859639\n",
      "Epoch 436: MSE: 2.281311, MAE: 1.1330686\n",
      "Epoch 437: MSE: 2.3355412, MAE: 1.0718789\n",
      "Epoch 438: MSE: 2.1309392, MAE: 0.9938818\n",
      "Epoch 439: MSE: 2.3434312, MAE: 1.1304778\n",
      "Epoch 440: MSE: 2.2896674, MAE: 1.0561255\n",
      "Epoch 441: MSE: 2.3751764, MAE: 1.038917\n",
      "Epoch 442: MSE: 2.1401393, MAE: 1.0601698\n",
      "Epoch 443: MSE: 2.429105, MAE: 1.0729678\n",
      "Epoch 444: MSE: 2.131538, MAE: 1.0072672\n",
      "Epoch 445: MSE: 2.3500166, MAE: 1.1004932\n",
      "Epoch 446: MSE: 2.3567157, MAE: 1.0673223\n",
      "Epoch 447: MSE: 1.9852351, MAE: 1.020654\n",
      "Epoch 448: MSE: 2.4052706, MAE: 1.0610852\n",
      "Epoch 449: MSE: 2.3212051, MAE: 1.023895\n",
      "Epoch 450: MSE: 2.062363, MAE: 1.0348312\n",
      "Epoch 451: MSE: 1.9933267, MAE: 1.0064056\n",
      "Epoch 452: MSE: 2.1422668, MAE: 1.0859095\n",
      "Epoch 453: MSE: 2.1843646, MAE: 1.0581915\n",
      "Epoch 454: MSE: 2.3753583, MAE: 1.0767798\n",
      "Epoch 455: MSE: 2.189798, MAE: 1.0426209\n",
      "Epoch 456: MSE: 2.0287142, MAE: 1.0401423\n",
      "Epoch 457: MSE: 2.3764973, MAE: 1.0379543\n",
      "Epoch 458: MSE: 2.2836988, MAE: 1.0382503\n",
      "Epoch 459: MSE: 2.081289, MAE: 0.9916694\n",
      "Epoch 460: MSE: 2.4885726, MAE: 1.0698935\n",
      "Epoch 461: MSE: 2.0773354, MAE: 0.98057467\n",
      "Epoch 462: MSE: 2.1526566, MAE: 1.0344522\n",
      "Epoch 463: MSE: 2.2761815, MAE: 0.9977208\n",
      "Epoch 464: MSE: 2.1473286, MAE: 1.0172952\n",
      "Epoch 465: MSE: 2.2223396, MAE: 1.0272909\n",
      "Epoch 466: MSE: 2.1285825, MAE: 1.003764\n",
      "Epoch 467: MSE: 2.3283784, MAE: 1.1332797\n",
      "Epoch 468: MSE: 2.2100105, MAE: 0.99744326\n",
      "Epoch 469: MSE: 1.8799735, MAE: 0.9228827\n",
      "Epoch 470: MSE: 2.1087584, MAE: 1.149205\n",
      "Epoch 471: MSE: 2.538277, MAE: 1.0589067\n",
      "Epoch 472: MSE: 2.1284482, MAE: 0.9813346\n",
      "Epoch 473: MSE: 2.0404832, MAE: 1.0174538\n",
      "Epoch 474: MSE: 2.015666, MAE: 1.0651457\n",
      "Epoch 475: MSE: 2.2186568, MAE: 1.1117166\n",
      "Epoch 476: MSE: 1.9820033, MAE: 0.9885024\n",
      "Epoch 477: MSE: 2.1462603, MAE: 1.0942076\n",
      "Epoch 478: MSE: 2.2816386, MAE: 1.0784285\n",
      "Epoch 479: MSE: 2.3165405, MAE: 1.0171765\n",
      "Epoch 480: MSE: 1.8822434, MAE: 0.9593929\n",
      "Epoch 481: MSE: 2.0582597, MAE: 1.1123391\n",
      "Epoch 482: MSE: 2.434249, MAE: 1.0311205\n",
      "Epoch 483: MSE: 2.089879, MAE: 1.032398\n",
      "Epoch 484: MSE: 2.0784533, MAE: 1.0538758\n",
      "Epoch 485: MSE: 2.1620345, MAE: 1.0649906\n",
      "Epoch 486: MSE: 1.9281672, MAE: 1.0185384\n",
      "Epoch 487: MSE: 2.3936622, MAE: 1.1320926\n",
      "Epoch 488: MSE: 1.9670854, MAE: 0.98466235\n",
      "Epoch 489: MSE: 1.9933627, MAE: 1.0828221\n",
      "Epoch 490: MSE: 2.1991992, MAE: 1.0484401\n",
      "Epoch 491: MSE: 1.9376016, MAE: 1.0140437\n",
      "Epoch 492: MSE: 2.1922019, MAE: 1.0486553\n",
      "Epoch 493: MSE: 2.0114472, MAE: 1.0411222\n",
      "Epoch 494: MSE: 2.0711641, MAE: 1.0312551\n",
      "Epoch 495: MSE: 2.168018, MAE: 1.0387685\n",
      "Epoch 496: MSE: 2.1093874, MAE: 1.063495\n",
      "Epoch 497: MSE: 2.2149003, MAE: 0.9868644\n",
      "Epoch 498: MSE: 2.0038676, MAE: 1.0043914\n",
      "Epoch 499: MSE: 1.8853593, MAE: 0.9613872\n",
      "Epoch 500: MSE: 2.2837987, MAE: 1.1120921\n"
     ]
    }
   ],
   "source": [
    "for epoch in 1...epochCount {\n",
    "    var epochLoss: Float = 0\n",
    "    var epochMAE: Float = 0\n",
    "    var batchCount: Int = 0\n",
    "    var batchArray = Array(repeating: false, count: numberOfBatch)\n",
    "    for batch in 0..<numberOfBatch {\n",
    "        var r = batch\n",
    "        if shuffle {\n",
    "            while true {\n",
    "                r = Int.random(in: 0..<numberOfBatch)\n",
    "                if !batchArray[r] {\n",
    "                    batchArray[r] = true\n",
    "                    break\n",
    "                }\n",
    "            }\n",
    "        }\n",
    "        \n",
    "        let batchStart = r * batchSize\n",
    "        let batchEnd = min(numTrainRecords, batchStart + batchSize)\n",
    "        let (loss, grad) = model.valueWithGradient { (model: RegressionModel) -> Tensor<Float> in\n",
    "            let logits = model(XTrain[batchStart..<batchEnd])\n",
    "            return meanSquaredError(predicted: logits, expected: YTrain[batchStart..<batchEnd])\n",
    "        }\n",
    "        optimizer.update(&model, along: grad)\n",
    "        \n",
    "        let logits = model(XTrain[batchStart..<batchEnd])\n",
    "        epochMAE += mae(predictions: logits, truths: YTrain[batchStart..<batchEnd])\n",
    "        epochLoss += loss.scalarized()\n",
    "        batchCount += 1\n",
    "    }\n",
    "    epochMAE /= Float(batchCount)\n",
    "    epochLoss /= Float(batchCount)\n",
    "\n",
    "    print(\"Epoch \\(epoch): MSE: \\(epochLoss), MAE: \\(epochMAE)\")\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Test"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "MSE: 0.8232478, MAE: 0.070073694\r\n"
     ]
    }
   ],
   "source": [
    "Context.local.learningPhase = .inference\n",
    "\n",
    "let prediction = model(XTest)\n",
    "\n",
    "let predictionMse = meanSquaredError(predicted: prediction, expected: YTest).scalarized()/Float(numTestRecords)\n",
    "let predictionMae = mae(predictions: prediction, truths: YTest)/Float(numTestRecords)\n",
    "\n",
    "print(\"MSE: \\(predictionMse), MAE: \\(predictionMae)\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[ -0.30846816,   0.15054052,   -1.1039964,  -0.30756173,   0.05126577,   0.33352128,\r\n",
      "  0.024851447, -0.035726987,  -0.89119065,  -0.43651816,   -1.2319369,   0.42111015,\r\n",
      "  -0.93603975] [24.0] [[22.523558]]\r\n",
      "[  10.127699, -0.56208307,   1.3125796, -0.30756173,   1.4050479,  -0.8863933,   1.2248203,\r\n",
      "  -1.2581577,   2.6233904,   2.3634233,   0.9779132,  0.12650238,   1.6906141] [5.0] [[2.0903258]]\r\n",
      "[  2.8739426, -0.56208307,   1.3125796, -0.30756173,    1.108089,  -2.9993627,   1.2248203,\r\n",
      "  -1.3716108,   2.6233904,   2.3634233,   0.9779132, -0.23774466,   1.7431473] [11.9] [[15.41979]]\r\n",
      "[   1.541963, -0.56208307,   1.3125796, -0.30756173,   0.7150559, -0.93426037,   0.7972452,\r\n",
      "  -1.0169381,   2.6233904,   2.3634233,   0.9779132,   -2.180478,  0.39479825] [20.8] [[32.461395]]\r\n"
     ]
    }
   ],
   "source": [
    "print(XTrain[0], YTrain[0], model(XTrain[0].reshaped(to: TensorShape([1, 13]))))\n",
    "\n",
    "print(XTest[0], YTest[0], model(XTest[0].reshaped(to: TensorShape([1, 13]))))\n",
    "print(XTest[1], YTest[1], model(XTest[1].reshaped(to: TensorShape([1, 13]))))\n",
    "print(XTest[17], YTest[17], model(XTest[17].reshaped(to: TensorShape([1, 13]))))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab": {},
    "colab_type": "code",
    "id": "Fkf29HLlohIP"
   },
   "source": [
    "# Export"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[13, 64] [64, 32] [32, 1]\r\n",
      "[64] [32] [1]\r\n"
     ]
    }
   ],
   "source": [
    "print(model.layer1.weight.shape, model.layer2.weight.shape, model.layer3.weight.shape)\n",
    "print(model.layer1.bias.shape, model.layer2.bias.shape, model.layer3.bias.shape)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [],
   "source": [
    "let coremlModel = Model(version: 4,\n",
    "                        shortDescription: \"Regression\",\n",
    "                        author: \"Jacopo Mangiavacchi\",\n",
    "                        license: \"MIT\",\n",
    "                        userDefined: [\"SwiftCoremltoolsVersion\" : \"0.0.3\"]) {\n",
    "    Input(name: \"input\", shape: [13])\n",
    "    Output(name: \"output\", shape: [1])\n",
    "    NeuralNetwork {\n",
    "        InnerProduct(name: \"dense1\",\n",
    "                     input: [\"input\"],\n",
    "                     output: [\"outDense1\"],\n",
    "                     weight: model.layer1.weight.transposed().flattened().scalars,\n",
    "                     bias: model.layer1.bias.flattened().scalars,\n",
    "                     inputChannels: 13,\n",
    "                     outputChannels: 64)\n",
    "        ReLu(name: \"Relu1\",\n",
    "             input: [\"outDense1\"],\n",
    "             output: [\"outRelu1\"])\n",
    "        InnerProduct(name: \"dense2\",\n",
    "                     input: [\"outRelu1\"],\n",
    "                     output: [\"outDense2\"],\n",
    "                     weight: model.layer2.weight.transposed().flattened().scalars,\n",
    "                     bias: model.layer2.bias.flattened().scalars,\n",
    "                     inputChannels: 64,\n",
    "                     outputChannels: 32)\n",
    "        ReLu(name: \"Relu2\",\n",
    "             input: [\"outDense2\"],\n",
    "             output: [\"outRelu2\"])\n",
    "        InnerProduct(name: \"dense3\",\n",
    "                     input: [\"outRelu2\"],\n",
    "                     output: [\"output\"],\n",
    "                     weight: model.layer3.weight.transposed().flattened().scalars,\n",
    "                     bias: model.layer3.bias.flattened().scalars,\n",
    "                     inputChannels: 32,\n",
    "                     outputChannels: 1)\n",
    "    }\n",
    "}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [],
   "source": [
    "let coreMLData = coremlModel.coreMLData\n",
    "try! coreMLData!.write(to: URL(fileURLWithPath: \"../model/s4tf_train_model.mlmodel\"))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "colab": {
   "collapsed_sections": [],
   "name": "S4TF_House.ipynb",
   "provenance": []
  },
  "kernelspec": {
   "display_name": "Swift",
   "language": "swift",
   "name": "swift"
  },
  "language_info": {
   "file_extension": ".swift",
   "mimetype": "text/x-swift",
   "name": "swift",
   "version": ""
  }
 },
 "nbformat": 4,
 "nbformat_minor": 1
}
